/**
 * Class: GeometricNet.Network
 * Instance of GeometricNet.Network are used to create network object,
 * netwrok object manages all nework properties like edge,nodes,rules, graph etc
 */
GeometricNet.Network = OpenLayers.Class({
	/**
	 * APIProperty: name
	 * {string} name of the network
	 */
	name: null,
	/**
	 * APIProperty: map
	 * {<OpenLayers.Map>} map oject with which this network is associated
	 */
	map: null, 
	/**
	 * APIProperty: config
	 * {object}
	 * Network configuration
	 */  
	config: {},	
	/** 
	 * APIProperty: isTopology
	 *	{boolean}
	 *	used for network snap and association with edge , node 
	 */
	isToptolgoy: true,
	/**
	 * APIProperty: isSplitWithEdge
	 * {boolean} true in case of edge can be splitted with edge
	 */
	isSplitWithEdge: true,
	
	/**
	 * Property: nodesDetail
	 * {object}
	 */
	nodesDetail : null,
	/**
	 * Property: edgesDetail
	 * {object}
	 */
	edgesDetail : null,

	/** 
	 * Property : nodeSymbolizerLookup
	 */
	nodeSymbolizerLookup : null,  

	/** 
	 * Property : edgeSymbolizerLookup
	 */
	edgeSymbolizerLookup : null, 
	
	/** 
	 * APIProperty: fidURL
	 * {string}
	 *  url to fetch max fid of network component at server side
	 */
	 fidURL:null,
	
	/**
	 * Constructor: GeometricNet.Network
	 *
	 * Parameters:
	 * name - {string} name of the network
	 * map - 
	 * optrions - {oject} hashtable of extra options of network
	 */
	initialize: function(name,map,config){
		if (name == undefined && map == undefined && config == undefined) {
			return null;
		}		
		this.name=name;
		if (map instanceof OpenLayers.Map) {
			this.map =map;
		} else {
			return null;
		}
		this.config = config;
// 		if (options == undefined) {options={};}
// 		if(options.nodes){ this.nodesDetail = options.nodes;}
// 		if(options.edges){ this.edgesDetail = options.edges;}		
//		this.fidUrl = options.fidUrl ? options.fidUrl : null;

		// create node layer		
		this.node = this.createNodeLayer(this.config);
		this.node.network = this;
		map.addLayer(this.node);
		//create edge layer
		this.edge = this.createEdgeLayer(this.node,this.config);
		this.edge.network = this;
		map.addLayer(this.edge);
				
// 		var panel = new OpenLayers.Control.Panel({defaultControl: zb});
// 		panel.name = name+"_panel"
// 		var controls =[mouseDefault,zb];
//  		controls= controls.concat(this.createEdgeControls());
//  		controls= controls.concat(this.createNodeControls());		
//  		panel.addControls(controls);		
// 	  	this.map.addControl(panel);
// 
//  		var edgeToNodeSnap = new OpenLayers.Control.Snapping({ layer:this.edge ,targets:[{layer:this.node}] }); 
//  		this.map.addControl(edgeToNodeSnap);
//  		edgeToNodeSnap.activate();
//  		var nodeToEdgeSnap = new OpenLayers.Control.Snapping({ layer:this.node ,targets:[{layer:this.edge}] }); 
//  		this.map.addControl(nodeToEdgeSnap);
//  		nodeToEdgeSnap.activate();            
//  		var edgeToEdgeSnap = new OpenLayers.Control.Snapping({layer:this.edge});
//  		this.map.addControl(edgeToEdgeSnap);
//  		edgeToEdgeSnap.activate();
//  		var nodeToNodeSnap = new OpenLayers.Control.Snapping({layer:this.node});
//  		this.map.addControl(nodeToNodeSnap);
//  		nodeToNodeSnap.activate();
	},

	/**
	 * Method: createNodeLayer
	 * function to create network node layer
	 * Parameters:
	 * Returns:
	 * {<GeometricNet.Layer.Vector.Node>}
	 */
	createNodeLayer: function(networkConfig) {			
		var options={};		
		var defaultLookup = {};
		var symbolCount = 0;
		for (node in networkConfig.nodeLayer.nodes){
			if (networkConfig.nodeLayer.nodes[node].symbols) {
				defaultLookup[node] = networkConfig.nodeLayer.nodes[node].symbols.default;
				symbolCount++;
			}
		}
		if (symbolCount > 0){
			var styleMap = new OpenLayers.StyleMap();
			styleMap.addUniqueValueRules("default", networkConfig.nodeLayer.typeAttributeName,defaultLookup);
			options.styleMap = styleMap;		
		}
		options.projection = networkConfig.projection;
		if(networkConfig.nodeLayer.dataSource.strategies) {
			var strategies = [];
			for (var i=0;i<networkConfig.nodeLayer.dataSource.strategies.length;i++){			
				strategies.push(GeometricNet.Util.createStrategy(
					networkConfig.nodeLayer.dataSource.strategies[i]));
			}
	 		options.strategies =strategies;
 		}
 		if(networkConfig.nodeLayer.dataSource.protocol) {
	 		var format = GeometricNet.Util.createFormat(
	 						networkConfig.nodeLayer.dataSource.format);
	 		var protocol = GeometricNet.Util.createProtocol(
	 						networkConfig.nodeLayer.dataSource.protocol,
	 						networkConfig.nodeLayer.dataSource.url,format);
	 		options.protocol = protocol;
 		} 		
		options.network = this; 
		var nodeLayer = new GeometricNet.Layer.Vector.Node(this.name+"_node",options);		
		return nodeLayer;		
	},

	/**
	 * Method: createEdgeLayer
	 * function to create network edge layer
	 * Parameters:
	 * Returns:
	 * {<GeometricNet.Layer.Vector.Edge>}
	 */
	createEdgeLayer: function(node,networkConfig) {		
		var options={};
		var defaultLookup = {};
		var symbolCount = 0;
		for (edge in networkConfig.edgeLayer.edges){
			if(networkConfig.edgeLayer.edges[edge].symbols) {
				defaultLookup[edge] = networkConfig.edgeLayer.edges[edge].symbols.default;
				symbolCount++;
			}
		}
		if (symbolCount> 0) {
			var styleMap = new OpenLayers.StyleMap();
			styleMap.addUniqueValueRules("default", networkConfig.edgeLayer.typeAttributeName,defaultLookup);
			options.styleMap = styleMap;		
		}
		options.projection = networkConfig.projection;
		if (networkConfig.edgeLayer.dataSource.strategies) {
			var strategies = [];
			for (var i=0; i<networkConfig.edgeLayer.dataSource.strategies.length;i++){
				strategies.push(GeometricNet.Util.createStrategy(
					networkConfig.edgeLayer.dataSource.strategies[i]));
			}
	 		options.strategies =strategies;
 		}
 		if (networkConfig.edgeLayer.dataSource.protocol) {
	 		var format = GeometricNet.Util.createFormat(
	 						networkConfig.edgeLayer.dataSource.format);
	 		var protocol = GeometricNet.Util.createProtocol(
	 						networkConfig.edgeLayer.dataSource.protocol,
	 						networkConfig.edgeLayer.dataSource.url,format);
	 		options.protocol = protocol; 		
 		}
		options.network = this; 
		var edgeLayer = new GeometricNet.Layer.Vector.Edge(this.name+"_edge",node,options);		
		return edgeLayer;	
	},
	
	/**
	 * APIMethod: createNodeControls
	 * create network features edge,node layers and control   
	 * Parameters:	 
	 */
	createNodeControls: function(){
		var controls=[];
		for (node in this.config.nodeLayer.nodes){
			var isEditable = this.config.nodeLayer.nodes[node].isEditable ? 
				this.config.nodeLayer.nodes[node].isEditable : true;			
			if(isEditable && this.config.nodeLayer.nodes[node].controlOptions) {
				this.config.nodeLayer.nodes[node].controlOptions.nodeType = node; 
				controls.push(new GeometricNet.Control.DrawFeature.DrawNode(
					this.node,OpenLayers.Handler.Point,this.config.nodeLayer.nodes[node].controlOptions));
			}
		}
// 		if(this.nodesDetail){
// 			for (key in this.nodesDetail){
// 				//nodeTypes.push(this.nodesDetail[i].name);
// 				this.nodesDetail[key].controlOptions.nodeType=key;
// 				controls.push(new GeometricNet.Control.DrawFeature.DrawNode(
// 							this.node, OpenLayers.Handler.Point,this.nodesDetail[key].controlOptions));			
// 			}
// 		} 
		return controls;
	},
		
	/**
	 * APIMethod: createEdgeControls
	 * create network features edge,node layers and control   
	 * Parameters:	 
	 */
	createEdgeControls: function(){
		var controls=[];
		for (edge in this.config.edgeLayer.edges){
			var isEditable = this.config.edgeLayer.edges[edge].isEditable ? 
				this.config.edgeLayer.edges[edge].isEditable : true;			
			if(isEditable && this.config.edgeLayer.edges[edge].controlOptions) {
				this.config.edgeLayer.edges[edge].controlOptions.edgeType = edge; 
				controls.push(new GeometricNet.Control.DrawFeature.DrawEdge(
					this.edge,OpenLayers.Handler.Path,this.config.edgeLayer.edges[edge].controlOptions));
			}
		}
		
// 		if(this.edgesDetail){
// 			for (key in this.edgesDetail){
// 				//edgeTypes.push(edgesDetail[i].name);
// 				this.edgesDetail[key].controlOptions.edgeType=key;
// 				controls.push(new GeometricNet.Control.DrawFeature.DrawEdge(
// 							this.edge, OpenLayers.Handler.Path,this.edgesDetail[key].controlOptions));			
// 			}
// 		}		
		return controls;
	},

	/**
	 * APIMethod: createEditPanel
	 * Create control panel with editable feature control
	 * Parameters:
	 * isSnapping - {boolean}
	 * Returns: 
	 * {OpenLayers.Control.Panel}
	 */
	createEditPanel: function(isSnapping){
		var panel = new OpenLayers.Control.Panel();
		panel.name = this.name+"_editPanel";
		var controls =[];
 		controls= controls.concat(this.createEdgeControls());
 		controls= controls.concat(this.createNodeControls());		
 		panel.addControls(controls);		
	  	//this.map.addControl(panel);
		if (isSnapping){
	 		var edgeToNodeSnap = new OpenLayers.Control.Snapping({ layer:this.edge ,targets:[{layer:this.node}] }); 
	 		this.map.addControl(edgeToNodeSnap);
	 		edgeToNodeSnap.activate();
	 		var nodeToEdgeSnap = new OpenLayers.Control.Snapping({ layer:this.node ,targets:[{layer:this.edge}] }); 
	 		this.map.addControl(nodeToEdgeSnap);
	 		nodeToEdgeSnap.activate();            
	 		var edgeToEdgeSnap = new OpenLayers.Control.Snapping({layer:this.edge});
	 		this.map.addControl(edgeToEdgeSnap);
	 		edgeToEdgeSnap.activate();
	 		var nodeToNodeSnap = new OpenLayers.Control.Snapping({layer:this.node});
	 		this.map.addControl(nodeToNodeSnap);
	 		nodeToNodeSnap.activate();	
 		}
 		return panel;	
	},
	
	/**
	 * APIProperty: getMaxFid
	 * get the max fid of network components node , edge
	 * and set at respective layer
	 * Parameters:
	 * component - {string}
	 * network componenct name "node" , "edge"
	 */
	getMaxFid: function(component,options) {
		params = {"component" : component};		
		if(this.config.fidUrl){
	        resp = OpenLayers.Request.GET({
	            url: this.config.fidUrl,
	            callback: this.parseFid.bind(this,component),
	            params: params,
	        });
    	}
    	return null;
	},

	/**
	 * Method: parseFid
	 * parse the response of the getMaxfid
	 */
	parseFid: function(component,response){
		if (response.status == 200)	{		
			if(component=="edge"){
				this.edge.maxFid = response.responseText;
				this.edge.lastFid = this.edge.maxFid;
			} else if (component == "node"){
				this.node.maxFid = response.responseText;
				this.node.lastFid = this.node.maxFid;			
			} else {
				console.log("component fid not set for : " + component); 
			}		
		}
	},


	CLASS_NAME: "GeometricNet.Network"
});